<?php

/**
 * Represents an HTTP request.
 */
class HTTP_Request
{
  function HTTP_Request()
  {
    $this->gateway_interface = $_SERVER['GATEWAY_INTERFACE'];
    $this->protocol = $_SERVER['SERVER_PROTOCOL'];
    $this->method = $_SERVER['REQUEST_METHOD'];
    $this->query_string = $_SERVER['QUERY_STRING'];
    $this->accept_language = $this->parse_accept_language_header();
  }

  /**
   * Parse an (optionally given) HTTP Accept-Language header into an associative array.
   * By default, $_SERVER['HTTP_ACCEPT_LANGUAGE'] is used to get the header.
   *
   * @return array An associative array of quality values keyed by language codes.
   */
  function parse_accept_language($header = null)
  {
    if ( is_null($header) ) $header = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

    $parsed_langs = array();
    $langs = explode(',', $header);

    foreach ($langs as $lang)
    {
      $lang_code = $quality = null;
      list($lang_code, $quality) = explode(';q=', $lang);

      if ( !isset($quality) ) $quality = 1;

      $parsed_langs[$lang_code] = $quality;
    }

    return $parsed_langs;
  }

  function negotiate_content_type($available_types)
  {
  }

  function negotiate_language($available_languages)
  {
    $acceptable_langs = parse_http_accept_language();
    $best_available_quality = 0;
    $best_available_code = "";

    foreach ($acceptable_langs as $lang_code => $quality)
    {
      if ( isset($available_languages[$lang_code]) and $quality > $best_available_quality )
      {
        $best_available_quality = $quality;
        $best_available_code = $lang_code;
      }
    }

    if ( !$best_available_quality )
      $best_available_code = $fallback_lang;

    $best_available_code;

    return $best_available_code;
  }

  function negotiate_charset($avaiable_charset)
  {
  }
}

/**
 * Represents an HTTP response.
 * XXX: Maybe use std PHP instead of encapsulating all that?
 */
class HTTP_Response
{
  var $content_type;
  var $content;
  var $language = 'en';
  var $charset = 'UTF8';
  var $vary = array('negotiate');
  var $status = '200 OK';

  function HTTP_Response()
  {
  }

  function respond()
  {
    $this->send_headers();
    $this->send_content();
  }

  function send_headers()
  {
  }

  function send_content()
  {
  }
}

/**
 * Represents an HTTP resource or a class of HTTP resources.
 */
class HTTP_Resource
{
  /**
   * Different representations of the same resource (URL) are called variants.
   */
  private var $request;
  private var $response;

  /**
   * Override this to set up things you want to have available for all request methods.
   */
  function HTTP_Resource()
  {
  }

  public function request_and_response($request)
  {
    $this->request(&$request);
    return $this->response;
  }

  public function request_and_respond($request)
  {
    $this->request(&$request);
    $this->response->respond;
  }

  public function request($request)
  {
    $this->request = &$request;
    $this->response = HTTP_Response->new;

    // Call the correct request handler method depending on the request method
    if ( method_exists($this, $this->request->method) )
    {
      call_user_func(array($this, $this->request->method));
    }
    else
    {
      $this->response->set_status('405: Method Not Supported');
    }
  }

  /**
   * XXX: Can I even override PHP's native handling for this?
   * http://blog.taragana.com/index.php/archive/how-to-respond-to-http-head-request-from-php/
   */
  public function head()
  {
    return $this->get();
  }

  public function get()
  {
  }

  public function put()
  {
    $this->response->set_status('405: Method Not Supported');
  }

  public function delete()
  {
    $this->response->set_status('405: Method Not Supported');
  }

  public function post()
  {
    $this->response->set_status('405: Method Not Supported');
  }
}

?>
